--
-- Author:      name
-- DateTime:    2018-04-27 10:59:15
-- Description: 节点间消息转发，服务间消息转发


local skynet = require "skynet"
local cluster = require("skynet.cluster")
local httpc = require("http.httpc")
local cjson = require("cjson")
---------------------------------------------------------
-- class
---------------------------------------------------------
local NodeMessage = class("NodeMessage")

function NodeMessage:ctor(message_pack)
	self.message_pack = message_pack
	self.db_server = skynet.getenv("db_cluster_id")
	self.web_host = "127.0.0.1:8001"
end

--发送消息给客户端
--conn_type 连接的类型socket websocket
function NodeMessage:sendClient(fd, conn_type, message_name, body)
    print("___sendClient___", message_name)    
	self.message_pack:send(fd, conn_type, message_name, body)
	
end


---------------------------------------------------------
-- 不同进程服务间发送消息
---------------------------------------------------------
--异步发送消息请求 node:节点名, address服务名, cmd消息名
function NodeMessage:sendNode(node, address, cmd, ... )
	-- print("############", node, address, cmd, ... )
	local ok, result = x_pcall(cluster.send, node, address, cmd, ...)
	if not ok then
		error_log('##############NodeMessage.send faild:',result)
	end
	return result
end

--同步发送消息请求
function NodeMessage:callNode(node, address, cmd, ... )	
	-- print("________callNode ___",node, address, cmd, ...)
	local ok, res = pcall(cluster.call, node, address, cmd, ...)	
	if not ok then
		error_log("############NodeMessage.call cmd:"..cmd.." faild:", res, node, address, cmd, ...)
		return false
	end
	return res
end

--异步发送到指定节点的.manager服务
function NodeMessage:sendNodeProxy(node, cmd, ...)
	self:sendNode(node,'.manager', cmd, ...)
end

--同步发送到指定节点的.manager服务
function NodeMessage:callNodeProxy(node, cmd, ...)
	return self:callNode(node,'.manager', cmd, ...)
end


--异步发送到指定节点的.manager服务
function NodeMessage:sendNodeManager(node, cmd, ...)
	self:sendNode(node,'.manager', cmd, ...)
end

--同步发送到指定节点的.manager服务
function NodeMessage:callNodeManager(node, cmd, ...)
	local waiting_co = coroutine.running()
	local res = nil
	local function call_wrapper( ... )
		res = self:callNode(node, '.manager', cmd, ...)
		skynet.wakeup(waiting_co)
	end
    skynet.fork(call_wrapper,...)    
    --超时返回失败
    local timeout = timeout or 5
    if skynet.sleep(timeout * 100) == 'BREAK' then    	
        return true, res
    end
    error_log("__callNodeManager__发送消息超时___", cmd)
	return false, "发送消息超时,"..cmd
end


---------------------------------------------------------
-- 同进程服务间发送消息
---------------------------------------------------------
--同步给服务发消息
function NodeMessage:callService(service_name, cmd, ...)
	-- print("____service_name,",service_name)
	local ok, res = pcall(skynet.call, service_name,'lua',cmd,...)
	if ok then 
		return res
	end
	return false
end
--异步给服务发消息
function NodeMessage:sendService(service_name, cmd, ...)
	skynet.send(service_name,'lua',cmd,...)
end
--异步发送到指定节点的.manager服务
function NodeMessage:sendManager(cmd, ...)
	self:sendService('.manager',cmd,...)
end
--同步发送到指定节点的.manager服务
function NodeMessage:callManager(cmd, ...)
	return self:callService('.manager',cmd,...)
end


---------------------------------------------------------
-- db进程间发送消息
---------------------------------------------------------
function NodeMessage:sendDbProxy(cmd, sync_id, ...)
	self:sendNode(self.db_server,'.manager', cmd, sync_id, ...)
end
function NodeMessage:callDbProxy(cmd, sync_id, ...)
	return self:callNode(self.db_server,'.manager', cmd, sync_id, ...)
end

--直接操作redis
function NodeMessage:callDbRedis(sync_id, cmd, ...)
	return self:callDbProxy('executeRedis', sync_id, cmd, ...)
end

--直接操作mysql 传入sql名句, 用于复杂的操作
function NodeMessage:callDbMySql(sql, sync_id)
	return self:callDbProxy('executeMySql', sql, sync_id)
end

--传入table的方式操作mysql
function NodeMessage:callDbMySqlEx(cmd, tbname, field_values, where_field_values, sync_id)
	return self:callDbProxy('executeMySqlEx',cmd, tbname, field_values, where_field_values, sync_id)
end


---------------------------------------------------------
-- gate进程间发送消息
---------------------------------------------------------
function NodeMessage:sendUser(node, user_id, cmd, ...)
	-- print("______sendUser(____", user_id, cmd)
	self:sendNodeProxy(node, 'message_to_user_nt', user_id, cmd, ...)
end
function NodeMessage:sendUsers(node, users, cmd, ...)
	-- print("______sendUsers(____", users, cmd)
	self:sendNodeProxy(node, 'message_to_users_nt', users, cmd, ...)
end


---------------------------------------------------------
-- 给指定类型的服务器广播消息
---------------------------------------------------------
function NodeMessage:broadcastToServer(server_type, cmd, ...)
	local cluster_manager = global.cluster_manager
	local servers = cluster_manager:getServerByType(server_type)
	for k, v in pairs(servers) do 
		self:sendNodeProxy(v.cluster_addr, cmd, ...)
	end
end

---------------------------------------------------------
-- http请求
---------------------------------------------------------
function NodeMessage:httpGet(cmd, data)
	local ok, body = httpc.get(self.web_host, cmd, data)
	if not ok then 
		error_log("_________httpReq__error__", cmd, data)
		return 
	end
	return body
end

function NodeMessage:httpPost(cmd, data)
	local ok, body = httpc.post(self.web_host, cmd, data)
	if not ok then 
		error_log("_________httpReq__error__", cmd, data)
		return 
	end
	return body
end



return NodeMessage